import { CMEVENTS, IEnvironment } from '@amcax/base';
import { SKETCH_EVENT } from '@app-base/common/Constants';
import { httpSettingApi } from '@app-base/server/setting-http';
import { userEvents } from '@app-cad/module';
import { isEmpty } from 'lodash';
import {
  createContext,
  ReactNode,
  useContext,
  useEffect,
  useMemo,
  useReducer,
} from 'react';
import { ctx2 } from '../../module';
import {
  CAD_TYPE_TO_SCHEME,
  DEFAULT_MOUSE_GESTURE,
  DEFAULT_USER_HABIT,
  generateCustomControlSchemeConfig,
} from './const';

export enum EnvCAD {
  part_env, // 零件
  product_env, // 装配
  sketch_env, // 草图
}

// 前端到后端环境字段映射（下划线到驼峰）
export const ENV_FIELD_MAPPING = {
  part_env: 'partEnv',
  product_env: 'productEnv',
  sketch_env: 'sketchEnv',
};

// 后端到前端环境字段映射（驼峰到下划线）
export const ENV_FIELD_MAPPING_REVERSE = {
  partEnv: 'part_env',
  productEnv: 'product_env',
  sketchEnv: 'sketch_env',
};

export interface UserSetting {
  hiddenCommandIds?: Record<keyof typeof EnvCAD, string[]>;
  mouseGestureConfig: Record<keyof typeof EnvCAD, string[]> & {
    enableMouseGesture: boolean;
  };
  userHabit: CmdSettingSpace.UserHabit;
  currentEnvironment: keyof typeof EnvCAD;
}

// Action types
const SET_HIDDEN_COMMAND_ID = 'SET_HIDDEN_COMMAND_ID';
const SET_MOUSE_GESTURE_CONFIG = 'SET_MOUSE_GESTURE_CONFIG';
const SET_USER_HABIT = 'SET_USER_HABIT';
const SET_CURRENT_ENVIRONMENT = 'SET_CURRENT_ENVIRONMENT';

type UserSettingAction =
  | {
      type: typeof SET_HIDDEN_COMMAND_ID;
      payload: Record<keyof typeof EnvCAD, string[]>;
    }
  | {
      type: typeof SET_MOUSE_GESTURE_CONFIG;
      payload: Record<keyof typeof EnvCAD, string[]> & {
        enableMouseGesture: boolean;
      };
    }
  | { type: typeof SET_USER_HABIT; payload: CmdSettingSpace.UserHabit }
  | { type: typeof SET_CURRENT_ENVIRONMENT; payload: keyof typeof EnvCAD };

function userSettingReducer(
  state: UserSetting,
  action: UserSettingAction,
): UserSetting {
  switch (action.type) {
    case SET_HIDDEN_COMMAND_ID:
      return { ...state, hiddenCommandIds: action.payload };
    case SET_MOUSE_GESTURE_CONFIG:
      return { ...state, mouseGestureConfig: action.payload };
    case SET_USER_HABIT:
      return { ...state, userHabit: action.payload };
    case SET_CURRENT_ENVIRONMENT:
      return { ...state, currentEnvironment: action.payload };
    default:
      return state;
  }
}

export interface UserSettingContextType {
  hiddenCommandIds?: Record<keyof typeof EnvCAD, string[]>;
  mouseGestureConfig?: Record<keyof typeof EnvCAD, string[]> & {
    enableMouseGesture: boolean;
  };
  userHabit?: CmdSettingSpace.UserHabit;
  currentEnvironment?: keyof typeof EnvCAD;
  setHiddenCommandIds: (
    commands: Record<keyof typeof EnvCAD, string[]>,
  ) => void;
  setMouseGestureConfig: (
    params: Record<keyof typeof EnvCAD, string[]> & {
      enableMouseGesture: boolean;
    },
  ) => void;
  setUserHabit: (habit: CmdSettingSpace.UserHabit) => void;
  setCurrentEnvironment: (env: keyof typeof EnvCAD) => void;
}

const DEFAULT_FROZEN_COMMANDS = {
  part_env: [],
  product_env: [],
  sketch_env: [],
};

export const UserSettingContext = createContext<UserSettingContextType>(
  {} as UserSettingContextType,
);

export const useUserSettingCustomer = (): UserSettingContextType => {
  const context = useContext(UserSettingContext);
  if (!context) {
    throw new Error('useUserSetting 未找到');
  }
  return context;
};

export function UserSettingProvider({ children }: { children: ReactNode }) {
  const initialState = {
    hiddenCommandIds: DEFAULT_FROZEN_COMMANDS,
    mouseGestureConfig: DEFAULT_MOUSE_GESTURE,
    userHabit: DEFAULT_USER_HABIT,
    currentEnvironment: 'part_env' as keyof typeof EnvCAD,
  };

  const [userSetting, dispatch] = useReducer(userSettingReducer, initialState);

  // 根据CAD类型计算控制方案索引并设置
  const controlScheme = useMemo(() => {
    const modeToEnum = CAD_TYPE_TO_SCHEME.findIndex(
      (item) => item === (userSetting.userHabit.cadType ?? 'NEXT'),
    );

    // 设置控制方案
    if (
      !isNaN(modeToEnum) &&
      modeToEnum >= 0 &&
      modeToEnum <= 6 &&
      ctx2.viewer?.sceneSetup
    ) {
      ctx2.viewer.sceneSetup.setControlScheme(modeToEnum);
    }

    return modeToEnum;
  }, [userSetting.userHabit, ctx2.viewer]);

  // 为自定义控制方案设置配置
  useEffect(() => {
    // 仅在选择自定义方案(index=6)时执行
    if (controlScheme === 6 && ctx2.viewer?.sceneSetup) {
      const customConfig = userSetting.userHabit.customConfig;

      if (customConfig) {
        const finalCustomConfig =
          generateCustomControlSchemeConfig(customConfig);

        if (finalCustomConfig) {
          ctx2.viewer.sceneSetup.setCustomControlScheme(finalCustomConfig);
        }
      }
    }
  }, [controlScheme, userSetting.userHabit, ctx2.viewer]);

  // 将后端驼峰命名转换为前端下划线命名
  function convertToFrontendFormat(backendData) {
    if (!backendData) {
      return DEFAULT_FROZEN_COMMANDS;
    }

    return {
      part_env: backendData.partEnv || [],
      product_env: backendData.productEnv || [],
      sketch_env: backendData.sketchEnv || [],
    };
  }

  // 设置冻结命令
  function setHiddenCommandIds(
    commands: Record<keyof typeof EnvCAD, string[]>,
  ) {
    dispatch({
      type: SET_HIDDEN_COMMAND_ID,
      payload: commands,
    });
  }

  // 设置鼠标手势配置
  function setMouseGestureConfig(
    config: Record<keyof typeof EnvCAD, string[]> & {
      enableMouseGesture: boolean;
    },
  ) {
    dispatch({
      type: SET_MOUSE_GESTURE_CONFIG,
      payload: config,
    });
  }

  // 设置用户操作习惯
  function setUserHabit(habit: CmdSettingSpace.UserHabit) {
    dispatch({
      type: SET_USER_HABIT,
      payload: habit,
    });
  }

  // 设置当前环境
  function setCurrentEnvironment(env: keyof typeof EnvCAD) {
    dispatch({
      type: SET_CURRENT_ENVIRONMENT,
      payload: env,
    });
  }

  // 1. 获取命令配置
  async function fetchCmdConfig() {
    try {
      const response = await httpSettingApi.getUserCmdConfigDetail();
      const commandConfig = response.data;

      if (isEmpty(commandConfig)) {
        setHiddenCommandIds(DEFAULT_FROZEN_COMMANDS);
      } else {
        const frozenCommands = convertToFrontendFormat(commandConfig);
        dispatch({
          type: SET_HIDDEN_COMMAND_ID,
          payload: frozenCommands,
        });
      }
    } catch (error) {
      console.error('获取命令配置失败:', error);
    }
  }

  // 2. 获取鼠标手势配置
  async function fetchGestureConfig() {
    try {
      const response = await httpSettingApi.getUserMouseGestureDetail();
      const gestureConfig = response.data;

      if (!isEmpty(gestureConfig)) {
        const convertedConfig = {
          enableMouseGesture: gestureConfig.enableMouseGesture,
          part_env: gestureConfig.partEnv || [],
          sketch_env: gestureConfig.sketchEnv || [],
          product_env: gestureConfig.productEnv || [],
        };

        dispatch({
          type: SET_MOUSE_GESTURE_CONFIG,
          payload: convertedConfig,
        });
      }
    } catch (error) {
      console.error('获取鼠标手势配置失败:', error);
    }
  }

  // 3. 获取用户操作习惯配置
  async function fetchUserHabit() {
    try {
      const response = await httpSettingApi.getUserHabitDetail();
      const habitData = response.data;

      if (!isEmpty(habitData)) {
        const userHabit: CmdSettingSpace.UserHabit = {
          toolbarPosition:
            habitData.toolbarPosition || DEFAULT_USER_HABIT.toolbarPosition,
          cadType: habitData.cadType || DEFAULT_USER_HABIT.cadType,
          customConfig: habitData.customConfig || null,
        };

        dispatch({
          type: SET_USER_HABIT,
          payload: userHabit,
        });
      }
    } catch (error) {
      console.error('获取用户操作习惯失败:', error);
    }
  }

  // 并行获取所有配置
  async function fetchConfigurations() {
    try {
      await Promise.all([
        fetchCmdConfig(),
        fetchGestureConfig(),
        fetchUserHabit(),
      ]);
    } catch (error) {
      console.error('初始化配置失败:', error);
    }
  }

  // 处理环境变化转化
  const onSketchEventChange = ({ type }: { type: string; oldId?: string }) => {
    if (type === 'sketchIn') {
      setCurrentEnvironment('sketch_env');
    } else if (type === 'sketchOut') {
      setCurrentEnvironment('part_env');
    }
  };

  // 初始化和清理
  useEffect(() => {
    fetchConfigurations();

    // 设置事件监听
    const electronCenter = (window as any)?.electronCenter;
    if (electronCenter) {
      // 监听控制方案变更
      electronCenter.on(CMEVENTS.CONTROL_SCHEME_CHANGED, () => {
        fetchUserHabit();
      });

      // 监听自定义控制方案变更
      electronCenter.on(CMEVENTS.CUSTOM_CONTROL_SCHEME_CHANGED, () => {
        fetchUserHabit();
      });
    }

    userEvents.on(CMEVENTS.ENV_CHANGED, (env: IEnvironment) => {
      if (env.id === 'NextCAD') {
        setCurrentEnvironment('part_env');
      } else if (env.id === 'Product') {
        setCurrentEnvironment('product_env');
      }
    });
    // 监听草图环境变化
    userEvents.on(SKETCH_EVENT.SKETCH_EVENT_CHANGE, onSketchEventChange);

    return () => {
      if (electronCenter) {
        electronCenter.off(CMEVENTS.CONTROL_SCHEME_CHANGED);
        electronCenter.off(CMEVENTS.CUSTOM_CONTROL_SCHEME_CHANGED);
      }
      userEvents.off(SKETCH_EVENT.SKETCH_EVENT_CHANGE);
    };
  }, []);

  // 创建上下文值
  const value = useMemo(
    () => ({
      ...userSetting,
      setHiddenCommandIds,
      setMouseGestureConfig,
      setUserHabit,
      setCurrentEnvironment,
    }),
    [userSetting],
  );

  return (
    <UserSettingContext.Provider value={value}>
      {children}
    </UserSettingContext.Provider>
  );
}
